package top.anydata.lifeofcode.lifesystem.service.app.impl;

import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Pageable;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import top.anydata.lifeofcode.lifesystem.conf.ConstansKey;
import top.anydata.lifeofcode.lifesystem.dao.app.user.IAppUserRepository;
import top.anydata.lifeofcode.lifesystem.dto.app.AppUserDto;
import top.anydata.lifeofcode.lifesystem.entity.app.user.AppUserEntity;
import top.anydata.lifeofcode.lifesystem.service.app.IAppUserService;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 功能描述:
 *
 * @author <a href="mailto:caingao@anydata.top">CainGao</a>
 * @version V_1.0
 * @date 2024/5/8 3:27 PM
 */
@Slf4j
@Service
public class AppUserServiceImpl implements IAppUserService {

    IAppUserRepository appUserRepository;

    RedisTemplate<String, Object> redisTemplate;

    private final ModelMapper modelMapper = new ModelMapper();


    public AppUserServiceImpl(IAppUserRepository appUserRepository, RedisTemplate<String, Object> redisTemplate) {
        this.appUserRepository = appUserRepository;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void register(AppUserDto appUserDto) {
        AppUserEntity appUserEntity =new AppUserEntity();
        modelMapper.map(appUserDto,appUserEntity);
        appUserRepository.save(appUserEntity);
    }

    @Override
    public void location(Long userId, Point point) {
        redisTemplate.opsForGeo().add(ConstansKey.APP_USER_LOCATION_RK,point,userId);
    }

    @Override
    public List<AppUserDto> findNearby(Point point, Pageable pageable) {
        List<AppUserDto> appUserDtos = new ArrayList<>();
        Distance distance = new Distance(3000, Metrics.KILOMETERS);
        Circle circle = new Circle(point, distance);
        int offset = pageable.getPageNumber()*pageable.getPageSize();
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeCoordinates().includeDistance();
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results =
                redisTemplate.opsForGeo().radius(ConstansKey.APP_USER_LOCATION_RK, circle, args);
        if (results != null) {
            List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = results.getContent();
            log.info("content:{}",content);
            if (offset < content.size()) {
                List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> pagedResults = content.subList(offset, Math.min(offset + pageable.getPageSize(), content.size()));
                List<Long> userIds = new ArrayList<>();
                for (GeoResult<RedisGeoCommands.GeoLocation<Object>> result : pagedResults) {
                    log.info(result.getContent().getName() + " " + result.getDistance().getValue() + " " + result.getDistance().getUnit());
                    userIds.add((Long)result.getContent().getName());
                }
                log.info("userIds:{}",userIds);
            }
        }
        return appUserDtos;
    }

}
